package com.stark.commons.lang.util;

import org.apache.commons.lang3.StringUtils;

/**
 * IP 地址工具类。
 * @author Ben
 * @since 1.0.0
 * @version 1.0.0
 */
public class IpUtil {
	
	/**
	 * 判断字符串是否是 ip 地址。
	 * <p>如 192.168.1.0 或 202.24.0.0/14 返回 {@literal true} 。
	 * @param ip 字符串。
	 * @return 是返回 {@literal true} ，否则返回 {@literal false} 。
	 */
	public static boolean isIp(String ip) {
		if (StringUtils.isBlank(ip)) {
			return false;
		}
		ip = ip.trim();
		
		// 校验子网掩码
		if (ip.contains("/")) {
			int subnetMask = -1;
			try {
				subnetMask = Integer.parseInt(StringUtils.substringAfter(ip, "/"));
			} catch (Exception e) {
				return false;
			}
			if (subnetMask < 0 || subnetMask > 32) {
				return false;
			}
			ip = StringUtils.substringBefore(ip, "/");
		}
		
		String[] array = ip.split("\\.");
		if (array.length != 4) {
			return false;
		}
		for (String item : array) {
			int i = -1;
			try {
				i = Integer.parseInt(item);
			} catch (Exception e) {
				return false;
			}
			if (i < 0 || i > 255) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 判断 ip 地址是否在范围内。
	 * @param ip ip 地址。
	 * @param ipRange ip 地址段，如 192.168.1.0/24 或 202.24.0.0/14 。
	 * @return ip 在地址段内返回 <code>true</code> ，否则返回 <code>false</code> 。
	 */
	public static boolean isInRange(String ip, String ipRange) {
        String[] ips = ip.split("\\.");
        int ipAddr = (Integer.parseInt(ips[0]) << 24)
        		| (Integer.parseInt(ips[1]) << 16)
                | (Integer.parseInt(ips[2]) << 8)
                | Integer.parseInt(ips[3]);
        int type = Integer.parseInt(ipRange.replaceAll(".*/", ""));
        int mask = 0xFFFFFFFF << (32 - type);
        String cidrIp = ipRange.replaceAll("/.*", "");  
        String[] cidrIps = cidrIp.split("\\.");  
        int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24)
                | (Integer.parseInt(cidrIps[1]) << 16)
                | (Integer.parseInt(cidrIps[2]) << 8)
                | Integer.parseInt(cidrIps[3]);
        return (ipAddr & mask) == (cidrIpAddr & mask);
    }

}
